#pragma once

#include <iostream>
#include <semaphore.h>
#include <pthread.h>
#include <vector>
#include <unistd.h>
using namespace std;

#define default_value 3
template <class T>
class annular_queue
{
public:
    annular_queue(size_t n = default_value)
        : _v(5), _num(n), _proc(0), _cons(0)
    {
        sem_init(&_space, 0, n);
        sem_init(&_data, 0, 0);
        pthread_mutex_init(&_pmutex,nullptr);
        pthread_mutex_init(&_cmutex,nullptr);
    }
    void push(const T &x)
    {
        sem_wait(&_space); // P操作，分配信号量，成功则-1
        pthread_mutex_lock(&_pmutex);//先分配各个线程的信号量，再一个个访问，提高效率
        _v[_proc++] = x;
        _proc %= _num;
        sem_post(&_data); // V操作，数据++
        pthread_mutex_unlock(&_pmutex);
    }
    void pop(T *ret)
    {
        sem_wait(&_data); // P操作，分配信号量，成功则-1
        pthread_mutex_lock(&_cmutex);
        *ret = _v[_cons++];
        _cons %= _num;
        sem_post(&_space); // V操作，数据++
        pthread_mutex_unlock(&_cmutex);
    }
    ~annular_queue()
    {
        sem_destroy(&_space);
        sem_destroy(&_data);
    }

private:
    vector<T> _v;
    size_t _num;
    int _proc; // 生产者访问下标
    int _cons; // 消费者访问下标
    sem_t _space;
    sem_t _data;
    pthread_mutex_t _pmutex;
    pthread_mutex_t _cmutex;
};
